package com.hushan.audio;

import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.avdevice.AVDeviceInfoList;
import org.bytedeco.ffmpeg.avformat.AVFormatContext;
import org.bytedeco.ffmpeg.avformat.AVInputFormat;
import org.bytedeco.ffmpeg.avutil.AVDictionary;
import org.bytedeco.ffmpeg.global.avdevice;
import org.bytedeco.ffmpeg.global.avformat;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacpp.Pointer;
import org.bytedeco.javacpp.PointerPointer;

import jakarta.enterprise.context.ApplicationScoped;
import java.util.ArrayList;
import java.util.List;

/**
 * FFmpeg设备检测器 - 使用FFmpeg API检测音频设备
 * 解决GraalVM native模式下AudioSystem.getMixerInfo()返回空的问题
 */
@ApplicationScoped
@Slf4j
public class FFmpegDeviceDetector {
    
    private volatile boolean initialized = false;
    
    /**
     * 初始化FFmpeg设备检测
     */
    private void initializeFFmpeg() {
        if (initialized) {
            return;
        }
        
        try {
            log.debug("初始化FFmpeg设备检测器");
            
            // 加载FFmpeg库
            Loader.load(avutil.class);
            Loader.load(avformat.class);
            Loader.load(avdevice.class);
            
            // 注册所有设备
            avdevice.avdevice_register_all();
            
            initialized = true;
            log.info("FFmpeg设备检测器初始化完成");
            
        } catch (Exception e) {
            log.error("FFmpeg设备检测器初始化失败", e);
            throw new RuntimeException("无法初始化FFmpeg设备检测", e);
        }
    }
    
    /**
     * 获取音频输入设备列表
     */
    public List<AudioMixerInfo> getAudioInputDevices() {
        initializeFFmpeg();
        
        List<AudioMixerInfo> devices = new ArrayList<>();
        
        try {
            // 获取合适的输入格式
            String inputFormatName = getSystemInputFormat();
            log.debug("使用输入格式: {}", inputFormatName);
            
            AVInputFormat inputFormat = avformat.av_find_input_format(inputFormatName);
            if (inputFormat == null) {
                log.warn("无法找到输入格式: {}", inputFormatName);
                return getDefaultDevices();
            }
            
            // 创建设备列表指针
            AVDeviceInfoList deviceList = new AVDeviceInfoList();

            
            // 枚举设备
            int result = avdevice.avdevice_list_input_sources(
                inputFormat, (BytePointer)null, (AVDictionary) null, deviceList);
                
            if (result < 0) {
                log.warn("FFmpeg设备枚举失败，错误码: {}, 使用默认设备", result);
                return getDefaultDevices();
            }
            
            // 解析设备列表
            devices = parseDeviceList(deviceList);
            
            // 清理资源
            avdevice.avdevice_free_list_devices(deviceList);
            
            if (devices.isEmpty()) {
                log.warn("FFmpeg未检测到任何音频设备，使用默认配置");
                return getDefaultDevices();
            }
            
            log.info("FFmpeg成功检测到 {} 个音频输入设备", devices.size());
            return devices;
            
        } catch (Exception e) {
            log.error("FFmpeg设备检测过程中发生错误", e);
            return getDefaultDevices();
        }
    }
    
    /**
     * 根据操作系统获取合适的输入格式
     */
    private String getSystemInputFormat() {
        String osName = System.getProperty("os.name").toLowerCase();
        
        if (osName.contains("windows")) {
            return "dshow"; // DirectShow for Windows
        } else if (osName.contains("linux")) {
            return "alsa"; // ALSA for Linux
        } else if (osName.contains("mac")) {
            return "avfoundation"; // AVFoundation for macOS
        } else {
            log.warn("未识别的操作系统: {}, 使用默认格式", osName);
            return "dshow"; // 默认使用Windows格式
        }
    }
    
    /**
     * 解析FFmpeg设备列表
     */
    private List<AudioMixerInfo> parseDeviceList(AVDeviceInfoList deviceList) {
        List<AudioMixerInfo> devices = new ArrayList<>();
        
        try {
            int deviceCount = deviceList.nb_devices();
            log.debug("设备数量: {}", deviceCount);
            
            if (deviceCount <= 0) {
                return devices;
            }
            
            // 获取设备信息数组
            PointerPointer<org.bytedeco.ffmpeg.avdevice.AVDeviceInfo> deviceArray = 
                deviceList.devices();
                
            if (deviceArray == null) {
                log.warn("设备数组为null");
                return devices;
            }
            
            for (int i = 0; i < deviceCount; i++) {
                try {
                    org.bytedeco.ffmpeg.avdevice.AVDeviceInfo deviceInfo = 
                        deviceArray.get(org.bytedeco.ffmpeg.avdevice.AVDeviceInfo.class, i);
                        
                    if (deviceInfo == null) {
                        continue;
                    }
                    
                    String deviceName = deviceInfo.device_name().getString();
                    String deviceDescription = deviceInfo.device_description().getString();
                    
                    if (deviceName == null || deviceName.trim().isEmpty()) {
                        continue;
                    }
                    
                    AudioMixerInfo mixerInfo = AudioMixerInfo.builder()
                        .index(i)
                        .name(deviceName)
                        .description(deviceDescription != null ? deviceDescription : deviceName)
                        .vendor("FFmpeg")
                        .version("1.0")
                        .build();
                        
                    devices.add(mixerInfo);
                    log.debug("检测到设备 [{}]: {} - {}", i, deviceName, deviceDescription);
                    
                } catch (Exception e) {
                    log.warn("解析设备 {} 时发生错误: {}", i, e.getMessage());
                }
            }
            
        } catch (Exception e) {
            log.error("解析设备列表时发生错误", e);
        }
        
        return devices;
    }
    
    /**
     * 获取默认设备配置（当FFmpeg检测失败时使用）
     */
    private List<AudioMixerInfo> getDefaultDevices() {
        log.info("使用FFmpeg默认音频设备配置");
        
        String osName = System.getProperty("os.name");
        return List.of(
            AudioMixerInfo.builder()
                .index(0)
                .name("Default Audio Input (FFmpeg)")
                .description("Default system audio input via FFmpeg - " + osName)
                .vendor("FFmpeg")
                .version("1.0")
                .build()
        );
    }
    
    /**
     * 检查FFmpeg设备检测是否可用
     */
    public boolean isFFmpegDeviceDetectionAvailable() {
        try {
            initializeFFmpeg();
            
            String inputFormatName = getSystemInputFormat();
            AVInputFormat inputFormat = avformat.av_find_input_format(inputFormatName);
            
            return inputFormat != null;
        } catch (Exception e) {
            log.debug("FFmpeg设备检测不可用: {}", e.getMessage());
            return false;
        }
    }
}